package handlers

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"grpc-jwt-yonghurenzheng/v2.1_jwt/config"
	"grpc-jwt-yonghurenzheng/v2.1_jwt/models"

	"github.com/golang-jwt/jwt/v4"
	"golang.org/x/crypto/bcrypt"
)

// 注册
func Register(w http.ResponseWriter, r *http.Request) {
	var user models.User
	if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
		http.Error(w, "请求数据错误", http.StatusBadRequest)
		return
	}

	// 密码加密
	hashed, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		http.Error(w, "密码加密失败", http.StatusInternalServerError)
		return
	}

	// 插入数据库
	_, err = config.DB.Exec("INSERT INTO users (username, password, email) VALUES (?, ?, ?)",
		user.Username, string(hashed), user.Email)
	if err != nil {
		http.Error(w, fmt.Sprintf("注册失败: %v", err), http.StatusInternalServerError)
		return
	}

	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(map[string]string{"message": "注册成功"})
}

// 统一 JSON 错误返回
func writeJSONError(w http.ResponseWriter, status int, msg string) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(map[string]string{"error": msg})
}

// Login 登录接口
func Login(w http.ResponseWriter, r *http.Request) {
    // 只允许 POST
    if r.Method != http.MethodPost {
        writeJSONError(w, http.StatusMethodNotAllowed, "只允许 POST 方法")
        return
    }

    w.Header().Set("Content-Type", "application/json")

    // 解析请求 JSON
    var loginReq models.User
    if err := json.NewDecoder(r.Body).Decode(&loginReq); err != nil {
        writeJSONError(w, http.StatusBadRequest, "请求 JSON 数据错误: " + err.Error())
        return
    }

    if loginReq.Username == "" || loginReq.Password == "" {
        writeJSONError(w, http.StatusBadRequest, "用户名或密码不能为空")
        return
    }

    // 从数据库查询用户
    var user models.User
    var hashedPwd string
    err := config.DB.QueryRow("SELECT id, username, password, email FROM users WHERE username = ?", loginReq.Username).
        Scan(&user.ID, &user.Username, &hashedPwd, &user.Email)

    if err == sql.ErrNoRows {
        writeJSONError(w, http.StatusUnauthorized, "用户不存在")
        return
    } else if err != nil {
        writeJSONError(w, http.StatusInternalServerError, "查询数据库失败: "+err.Error())
        return
    }

    // 校验密码
    if err := bcrypt.CompareHashAndPassword([]byte(hashedPwd), []byte(loginReq.Password)); err != nil {
        writeJSONError(w, http.StatusUnauthorized, "密码错误")
        return
    }

    // --- JWT 核心逻辑 ---
	// 1. 设置 token 过期时间，例如 24 小时
	expirationTime := time.Now().Add(24 * time.Hour)

	// 2. 创建 JWT claims
	claims := &models.Claims{
		UserID:   user.ID,
		Username: user.Username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(expirationTime),
		},
	}
	
	// 3. 使用指定的签名方法创建 token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 4. 使用密钥签名并获取完整的 token 字符串
	tokenString, err := token.SignedString(config.JWTKey)
	if err != nil {
		writeJSONError(w, http.StatusInternalServerError, "生成 Token 失败")
		return
	}
	// --- JWT 核心逻辑结束 ---

	json.NewEncoder(w).Encode(map[string]interface{}{
		"message":  "登录成功",
		"token":    tokenString,
	})
}


